home *** CD-ROM | disk | FTP | other *** search
/ Aminet 22 / Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso / Aminet / util / misc / Geld_Pruef.lha / geldschein-pruef.c < prev    next >
C/C++ Source or Header  |  1997-08-18  |  7KB  |  221 lines

  1. /*    Quelltext     : geldschein-pruef.c                */
  2. /*    Author        : Finn Jacobs                    */
  3. /*    Version        : 1.2a                        */
  4. /*    Revision    : v31.1                        */
  5. /*    Compiler    : Maxon-Cpp-v1.0                */
  6.  
  7. #pragma -        /* Maxon-Cpp-Option fuer Ansi-C-Mode !        */
  8.  
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12.  
  13. #define VERSION     "1.2a"
  14. #define DATE         "18-Aug-97"
  15.  
  16. /* Geldschein-Pruefungs-Verfahren mittels Diederischer Gruppen         */
  17. /* Diederische Gruppen sind spezielle Gruppen aus der Fuelle der abel-    */
  18. /* schen Gruppen. Eine direkte mathematische Definition kann man aus    */
  19. /* der Quelle entnehmen. Fuer das Verstaendnis der Sachen, muesste    */
  20. /* schon Kenntnis ueber die Lineare Algebra eingebracht werden.        */
  21.  
  22. /* Hierbei ist die 11-stellige Nummer mit dem Alphabet {0,1,...,9}     */
  23. /* versehen. Nach einsetzen ergibt sich folgende Tabelle :          */
  24.  
  25. /*  A | D | G | K | L | N | S | U | Y | Z                      */
  26. /*  --+---+---+---+---+---+---+---+---+---                     */
  27. /*  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9                      */
  28.  
  29. /*  Die Zuordnung der Buchstaben in den Kennzeichen der deutschen      */
  30. /*  Banknoten zu Elementen von {0,1,...,9}.                 */
  31.  
  32. /* Jede solche Nummer a1a2...a11 erfuellt die Pruefgleichung        */
  33. /*         T(a1)*T2(a2)*...*T10(a10)*a11 = 0            */
  34.  
  35. char     a[10] = "0123456789";
  36. char alpha[10] = "ADGKLNSUYZ";
  37.  
  38. char t[10][10] = {
  39.     "1576283094",        /* Permutation, die durch das Verfahren    */
  40.     "5803796142",        /* s.u. realisiert wird.        */
  41.     "8916043527",
  42.     "9453126870",
  43.     "4286573901",
  44.     "2793806415",
  45.     "7046913258",
  46.     "0123456789",
  47.     "1576283094",
  48.     "5803796142"
  49. };
  50.  
  51. /* Es zeigt sich, dass die VERHOEFF [1969] angegebene Permutation T der    */
  52. /* Bedingung   x*T(y) <> y *T(x) fuer alle x,y e {0,1,...,9} mit x <>y    */
  53. /* genuegt, so dass nach 8.8(i) und (ii) alle Einzelfehler und alle Ver    */
  54. /* tauschungen benachbarter Zeichen (ausser evtl. der beiden letzten)    */
  55. /* erkannt werden koennte. Zusaetzlich koennen noch weitere Fehlertypen    */
  56. /* zu hohen Prozentsaetzen erkannt werden.                */
  57.  
  58. /* Das 8-Pruefzeichen-Verfahren wird so generiert :            */
  59. /*                                    */
  60. /*      i * j  |  0<=j<=4  |  5<=h<=9                    */
  61. /*    ---------------------------------                */
  62. /*     0<=i<=4 |   R(i+j)  | 5+R(i+j)                    */
  63. /*    ---------------------------------                */
  64. /*     5<=i<=9 |  5+R(i-j) |  R(i-j)                    */
  65. /*                                    */
  66. /*    mit R(a) := a(mod 5)                        */
  67. /*              = Rest von a bei Division durch 5            */
  68. /*                                    */
  69. /* Somit ergibt sich eine schematische Tabelle und eine ausfuehrliche :    */
  70. /*                                    */
  71. /*        j                                */
  72. /*      * | 0 1 2 3 4 | 5 6 7 8 9                    */
  73. /*      --+-----------------------                    */
  74. /*    i 0 | 0 1 2 3 4 | 5 6 7 8 9                    */
  75. /*      1 | 1 2 3 4 0 | 6 7 8 9 5                    */
  76. /*      2 | 2 3 4 0 1 | 7 8 9 5 6                    */
  77. /*      3 | 3 4 0 1 2 | 8 9 5 6 7                    */
  78. /*      4 | 4 0 1 2 3 | 9 5 6 7 8                    */
  79. /*      --+-----------+-----------                    */
  80. /*      5 | 5 9 8 7 6 | 0 4 3 2 1                    */
  81. /*      6 | 6 5 9 8 7 | 1 0 4 3 2                    */
  82. /*      7 | 7 6 5 9 8 | 2 1 0 4 3                    */
  83. /*      8 | 8 7 6 5 9 | 3 2 1 0 4                    */
  84. /*      9 | 9 8 7 6 5 | 4 3 2 1 0                    */
  85. /*                                    */
  86. /*    Tabelle : von D5 induzierte Verknuepfung * auf {0,1,...,8,9}    */
  87. /*                                    */
  88. /*                                    */
  89. /*    Quelle : Codierungstheorie - Eine Einfuehrung (R.-H. Schulz)    */
  90. /*         ISBN : 3-528-06419-6  (Vieweg-Verlag)            */
  91.  
  92.  
  93. int fmod( int x, int y)
  94. {
  95.     /* Richtiges fmod, da fmod von math.h nicht richtig    */
  96.     /* funktioniert - jedenfalls funktionierte die Version    */
  97.     /* nicht in dieser Anwendung so, wie sie es eigentlich    */
  98.     /* sollte ;-)                        */
  99.  
  100.     /* (c) 1997 by F. Jacobs                */
  101.  
  102.     int a, b;
  103.  
  104.     if (x < 0) x += y;
  105.     if ((x == y) || (x == 0)) return(0);
  106.     while (x == 2*y) x -= 2*y;
  107.     while (x >= 2*y) x -= y;
  108.     while (x > y)  x -= y;
  109.     a = 0; b = 0;
  110.     while ( a<=y )
  111.     {
  112.         if (b >= y) break;
  113.         a++;
  114.         b += x;
  115.     }
  116.     return (b / a);
  117. }
  118.  
  119. double dieder( double i, double j)
  120. {
  121.     /* 8-Pruefzeichen-Verfahren : induzierte Verknuepfung *        */
  122.     /* auf {0,1,...,8,9}.                        */
  123.  
  124.     if (((i>=0) && (i<=4) && (j>=0) && (j<=4))) return( fmod( (i+j), 5) );
  125.     if (((i>=5) && (i<=9) && (j>=0) && (j<=4))) return( fmod( (i-j), 5) +5 );
  126.     if (((i>=0) && (i<=4) && (j>=5) && (j<=9))) return( fmod( (i+j), 5) +5 );
  127.     if (((i>=5) && (i<=9) && (j>=5) && (j<=9))) return( fmod( (i-j), 5) );
  128. }
  129.  
  130. void main(int argc, char *argv[])
  131. {
  132.     int i, j, errorcode = 0;
  133.  
  134.     printf("\033[1mGeldschein-Pruefung "VERSION" ("DATE") - von Finn Jacobs\033[0m\n");
  135.     if (argc <= 1)
  136.     {
  137.         printf("Usage : %s <geldscheinnummer> [-q]\n", argv[0]);
  138.         exit(0);
  139.     }
  140.     if (argv[2][0] == '-')
  141.     {
  142.         if (argv[2][1] == 'q')
  143.         {
  144.             errorcode = 1;
  145.         } else
  146.         {
  147.             printf("** FEHLER : - Option nicht bekannt!\n");
  148.             exit(10);
  149.         }
  150.     }
  151.     if (strlen(argv[1]) == 11)
  152.     {
  153.         printf("Zu ueberpruefende Nummer : %s\n", argv[1]);
  154.     } else {
  155.         printf("Nummer ist keine Pruefnummer !\n");
  156.         exit(5);
  157.     }
  158.  
  159.     /***** Argument in Zahlen codieren *****/
  160.     for (i=0; i < 11; i++)
  161.     {
  162.         for (j=0; j < 10; j++)
  163.         {
  164.             if (toupper(argv[1][i]) == alpha[j])
  165.             {
  166.                 argv[1][i] = a[j];
  167.             }
  168.         }
  169.     }
  170.     printf("Nummer wird codiert      : %s\n", argv[1]);
  171.  
  172.     /***** Argument wird mit Tabellen verknuepft *****/
  173.     argv[1][0] = t[0][argv[1][0]-48];
  174.     argv[1][1] = t[1][argv[1][1]-48];
  175.     argv[1][2] = t[2][argv[1][2]-48];
  176.     argv[1][3] = t[3][argv[1][3]-48];
  177.     argv[1][4] = t[4][argv[1][4]-48];
  178.     argv[1][5] = t[5][argv[1][5]-48];
  179.     argv[1][6] = t[6][argv[1][6]-48];
  180.     argv[1][7] = t[7][argv[1][7]-48];
  181.     argv[1][8] = t[8][argv[1][8]-48];
  182.     argv[1][9] = t[9][argv[1][9]-48];
  183.     printf("Permutation ergibt       : %s\n", argv[1]);
  184.  
  185.     /**** Argument wird jetzt geprueft *****/    
  186.  
  187.     argv[1][0] = dieder(argv[1][0]-48, argv[1][1]-48)+48;
  188.     argv[1][1] = dieder(argv[1][2]-48, argv[1][3]-48)+48;
  189.     argv[1][2] = dieder(argv[1][4]-48, argv[1][5]-48)+48;
  190.     argv[1][3] = dieder(argv[1][6]-48, argv[1][7]-48)+48;
  191.     argv[1][4] = dieder(argv[1][8]-48, argv[1][9]-48)+48;
  192.     argv[1][5] = argv[1][10];
  193.     argv[1][6] = 0;
  194.     printf("1. Pruefung              : %s\n", argv[1]);
  195.  
  196.     argv[1][0] = dieder(argv[1][0]-48, argv[1][1]-48)+48;
  197.     argv[1][1] = dieder(argv[1][2]-48, argv[1][3]-48)+48;
  198.     argv[1][2] = dieder(argv[1][4]-48, argv[1][5]-48)+48;
  199.     argv[1][3] = 0;
  200.     printf("2. Pruefung              : %s\n", argv[1]);
  201.  
  202.     argv[1][0] = dieder(argv[1][0]-48, argv[1][1]-48)+48;
  203.     printf("3. Pruefung              : %s\n", argv[1]);
  204.  
  205.     argv[1][0] = dieder(argv[1][0]-48, argv[1][2]-48)+48;
  206.     argv[1][1] = 0;
  207.     printf("4. Pruefung              : %s\n\n", argv[1]);
  208.  
  209.     if ((argv[1][0]-48)==0)
  210.     {
  211.         printf("Die Kennummer \033[1mexistiert\033[0m.\n\n");
  212.         if (errorcode == 1) exit(0);
  213.     } else
  214.     {
  215.         printf("Die Kennummer \033[1mgibt es nicht\033[0m !\n\n");
  216.         if (errorcode == 1) exit(1);
  217.     }
  218. }
  219.  
  220. /*    Ende des Quelltextes                        */
  221.